package com.youlu.campus.service.ca.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.youlu.campus.base.exception.*;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.CaCollectReq;
import com.youlu.campus.entity.VO.req.PointPlaceOrderVO;
import com.youlu.campus.entity.VO.req.UserCaQueryVO;
import com.youlu.campus.entity.VO.req.UserCaReceivePointReq;
import com.youlu.campus.entity.VO.res.CaCollectRes;
import com.youlu.campus.entity.VO.res.MyOrderResponse;
import com.youlu.campus.entity.VO.res.UserCaHonorRes;
import com.youlu.campus.entity.VO.res.UserCaReceivePointRes;
import com.youlu.campus.entity.ca.GiftCaInfo;
import com.youlu.campus.entity.ca.UserCa;
import com.youlu.campus.entity.course.ActivityCourse;
import com.youlu.campus.entity.domain.UserCaDomain;
import com.youlu.campus.entity.english.UserCompetition;
import com.youlu.campus.entity.english.vo.request.CompetitionCaCollectRequest;
import com.youlu.campus.entity.enums.ActivityVideoStatusEnum;
import com.youlu.campus.entity.enums.CaMaterialType;
import com.youlu.campus.service.activity.ActivityRewardRuleService;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.activity.impl.ActivityPayConfigService;
import com.youlu.campus.service.base.BaseService;
import com.youlu.campus.service.ca.*;
import com.youlu.campus.service.cache.CacheActivityService;
import com.youlu.campus.service.course.UserVideoService;
import com.youlu.campus.service.english.UserCompetitionQaCaService;
import com.youlu.campus.service.order.DigitalCaOrderDetailService;
import com.youlu.campus.service.order.OrderService;
import com.youlu.campus.service.platform.PointPlatformConfigService;
import com.youlu.campus.service.postage.PostageTemplateService;
import com.youlu.campus.service.ranking.UserActivityPointRankingService;
import com.youlu.campus.service.ranking.UserPointRankingService;
import com.youlu.campus.service.ranking.entity.UserActivityPointRanking;
import com.youlu.campus.service.visitor.UserAddressInfoService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import com.youlu.campus.service.visitor.UserPointsService;
import com.youlu.campus.service.university.UniversityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserCaServiceImpl extends BaseService implements UserCaService {


    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private PointPlatformConfigService pointPlatformConfigService;
    @Autowired
    private CacheActivityService cacheActivityService;
    @Autowired
    private PostageTemplateService postageTemplateService;

    @Autowired
    private UserInfoExtendService userInfoExtendService;
    @Autowired
    private UserPointsService userPointsService;
    @Autowired
    private UserCompetitionQaCaService userCompetitionQaCaService;

    @Autowired
    private UserCaReceiveRecordService userCaReceiveRecordService;

    @Autowired
    private CertificateActivityConfigService certificateActivityConfigService;

    @Autowired
    private UserAddressInfoService userAddressInfoService;

    @Lazy
    @Autowired
    private CaInfoService caInfoService;

    @Autowired
    private ActivityPayConfigService activityPayConfigService;


    @Lazy
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;

    @Autowired
    private UserPointRankingService userPointRankingService;

    @Autowired
    private CaCertificateConfigService caCertificateConfigService;

    @Autowired
    private UserActivityPointRankingService userActivityPointRankingService;

    @Autowired
    private ActivityRewardRuleService activityRewardRuleService;

    @Autowired
    private UserCaReceiveHistoryService userCaReceiveHistoryService;

    @Lazy
    @Autowired
    private OrderService orderService;

    @Autowired
    private CaCollectService caCollectService;

    @Autowired
    @Lazy
    private ActivityService activityService;


    @Autowired
    private UserVideoService userVideoService;

    @Autowired
    private CaPinYinService caPinYinService;

    @Autowired
    private UniversityService universityService;

    @Lazy
    @Autowired
    private DigitalCaOrderDetailService digitalCaOrderDetailService;

    @Resource(name = "masterMongoTemplate")
    private MongoTemplate masterMongoTemplate;

    @Async
    @Override
    public void create(UserCa req) {
        log.info("【证书信息生成】activityId - > {} | userId - >{} |level ->{}| catType - > {}", req.getActivityId(),
                req.getUserId(), req.getCaLevel(), req.getCaType());
        if (StringUtils.isBlank(req.getUserId())) {
            return;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(req.getUserId()));
        if (StringUtils.isNotBlank(req.getCaType())) {
            query.addCriteria(Criteria.where("caType").is(req.getCaType()));
        }
        if (StringUtils.isNotBlank(req.getCaLevel())) {
            query.addCriteria(Criteria.where("caLevel").is(req.getCaLevel()));
        }
        query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        Date now = new Date();
        Update update = new Update();
        Boolean exists = this.mongoTemplate.exists(query, UserCa.class);
        if (!exists) {
            update.set("createdTime", now);
        }
        update.set("updatedTime", now);
        if (StringUtils.isNotBlank(req.getCertificateActivityConfigId())) {
            update.set("certificateActivityConfigId", req.getCertificateActivityConfigId());
        }
        if (StringUtils.isNotBlank(req.getUniversityId())) {
            update.set("universityId", req.getUniversityId());
        }
        if (StringUtils.isNotBlank(req.getUniversityName())) {
            update.set("universityName", req.getUniversityName());
        }
        if (StringUtils.isNotBlank(req.getMoneyType())) {
            update.set("moneyType", req.getMoneyType());
        }
        if (StringUtils.isNotBlank(req.getMobile())) {
            update.set("mobile", req.getMobile());
        }
        if (StringUtils.isNotBlank(req.getName())) {
            update.set("name", req.getName());
        }
        if (StringUtils.isNotBlank(req.getActivityName())) {
            update.set("activityName", req.getActivityName());
        }
        if (Objects.nonNull(req.getScore())) {
            update.set("score", req.getScore());
        }
        if (StringUtils.isNotBlank(req.getCaLevel())) {
            update.set("caLevel", req.getCaLevel());
        }
        if (StringUtils.isNotBlank(req.getTaskBizType())) {
            update.set("taskBizType", req.getTaskBizType());
        }
        if (Objects.nonNull(req.getCertificateName())) {
            update.set("certificateName", req.getCertificateName());
        }
        if (StringUtils.isNotBlank(req.getPlatform())) {
            update.set("platform", req.getPlatform());
        }
        if (StringUtils.isNotBlank(req.getAppId())) {
            update.set("appId", req.getAppId());
        }
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.upsert(Boolean.TRUE);
        findAndModifyOptions.returnNew(Boolean.TRUE);
        this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UserCa.class);
    }

    @Override
    public Page<UserCa> list(UserCaQueryVO req) {
        log.info(":>>> 获取用户证书列表:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || Objects.isNull(req.getCaMaterialType())) {
            log.error(":>>> 获取证书列表参数错误");
            throw new BusinessException("获取证书列表参数错误");
        }
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
        if (req.getBizType() == 1) {
            Boolean exist = userInfoExtendService.existByUserId(req.getUserId());
            if (!exist) {
                log.error("【用户未报名】userId - > {}", req.getUserId());
                return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0);
            }
        }
        Query query = new Query();
        if (req.getBizType() == 2) {
            if (!StringUtils.isBlank(req.getTaskBizType())) {
                query.addCriteria(Criteria.where("taskBizType").is(req.getTaskBizType()));
            }
        }
        if (!StringUtils.isBlank(req.getUserId())) {
            query.addCriteria(Criteria.where("userId").is(req.getUserId()));
        }
        if (!StringUtils.isBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<UserCa> infos = mongoTemplate.find(query, UserCa.class);
        if (CollectionUtils.isEmpty(infos)) {
            return new PageImpl<>(new ArrayList<>());
        }
        if (req.getBizType() == 2) {
            UserActivityPointRanking userPointRanking =
                    userPointRankingService.findByUserIdAndActivityId(req.getUserId(), req.getActivityId());
            if (Objects.isNull(userPointRanking) || userPointRanking.getQuantity().compareTo(40D) == -1) {
                throw new UserPointException("满40积分可免费领取电子证书，您当前积分不足");
            }
            userParticipateActivityInfoService.checkUserInfoSignUp(req.getUserId(), req.getActivityId());
            return new PageImpl<>(infos);
        }
        List<String> userCaIds = infos.stream().map(userCa -> userCa.getUserId()).collect(Collectors.toList());
        int point = 0;
        //recieve-paper-ca:领取纸质版,recieve-digit-ca:领取电子版
        switch (req.getCaMaterialType()) {
            case DIGIT:
                point = pointPlatformConfigService.getPoint("recieve-digit-ca");
                break;
            case PAPER:
                point = pointPlatformConfigService.getPoint("recieve-paper-ca");
                break;
            default:
                break;
        }
        Map<String, List<UserCa>> userCaMap =
                infos.stream().collect(Collectors.groupingBy(userCa -> userCa.getActivityId() + "," + userCa.getCaType()));
        List<UserCa> userCaList = Lists.newArrayListWithCapacity(userCaMap.size());
        userCaMap.forEach((catType, caItem) -> {
            UserCa userCa =
                    caItem.stream().sorted(Comparator.comparing(UserCa::getScore).reversed()).collect(Collectors.toList()).get(0);
            userCaList.add(userCa);
        });

        final int p = point;
        Query queryDetail = new Query();
        queryDetail.addCriteria(Criteria.where("userCaId").in(userCaIds));
        queryDetail.addCriteria(Criteria.where("caMaterialType").is(req.getCaMaterialType()));
        List<UserCaReceiveRecord> recieveRecords = mongoTemplate.find(queryDetail, UserCaReceiveRecord.class);
        if (!CollectionUtils.isEmpty(recieveRecords)) {
            userCaList.stream().forEach(userCa -> {
                for (UserCaReceiveRecord userCaReceiveRecord : recieveRecords) {
                    if (CaMaterialType.PAPER.equals(userCaReceiveRecord.getMaterial()) && userCa.getId().equals(userCaReceiveRecord.getUserCaId())) {
                        userCa.setRecieved(true);
                    } else {
                        //电子证书领取验证v c
                        Boolean existReceive =
                                this.userCaReceiveRecordService.existCaByUserIdAndCaTypeAndActivityId(req.getUserId()
                                        , userCa.getCaType(), userCa.getActivityId(), CaMaterialType.DIGIT);
                        if (existReceive) {
                            userCa.setRecieved(true);
                        }
                    }
                }
                userCa.setPrice(p);
            });
        }
        userCaMap.clear();
        return new PageImpl<>(userCaList);
    }

    @Override
    public OrderInfo placeOrderByPoint(PointPlaceOrderVO req, UserPO userPO) {
        log.info(":>>> 开始积分下单:{},{}", JSON.toJSONString(req), JSON.toJSON(userPO));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getUserCaId()) || Objects.isNull(req.getUserAddressInfo())) {
            log.error(":>>> 用户下单参数错误:用户证书、地址信息为空");
            throw new BusinessException("用户积分下单参数错误");
        }
        Integer requirePoint = pointPlatformConfigService.getPoint("recieve-paper-ca");
        boolean hasPoint = userPointsService.hasPoint(userPO.getId(), req.getAppId(), "recieve-paper-ca");
        if (!hasPoint) {
            log.info(":>>> 用户:{} 积分不足", userPO.getId());
            throw new BusinessException("用户积分不足");
        }
        boolean checkAddress = userAddressInfoService.checkUserAddress(req.getUserAddressInfo());
        if (!checkAddress) {
            log.info(":>>> 用户地址错误");
            throw new BusinessException("用户地址错误");
        }
        if (StringUtils.isBlank(req.getUserAddressInfo().getId())) {
            userAddressInfoService.create(req.getUserAddressInfo());
        } else {
            userAddressInfoService.update(req.getUserAddressInfo());
        }
        UserCa userCa = this.findOne(req.getUserCaId());
        log.debug(":>>> 用户证书信息为:{}", JSON.toJSONString(userCa));
        if (Objects.isNull(userCa) || StringUtils.isBlank(userCa.getCertificateActivityConfigId())) {
            log.error(":>>> 用户证书不存在:{}", req.getUserCaId());
            throw new BusinessException("用户证书不存在");
        }
        CertificateActivityConfig caConfig =
                certificateActivityConfigService.detail(userCa.getCertificateActivityConfigId());
        if (Objects.isNull(caConfig)) {
            log.error(":>>> 用户证书配置错误:{}", userCa.getCertificateActivityConfigId());
            throw new BusinessException("用户证书配置错误");
        }

        String orderNo = super.generateOrderNo("证书");
        log.info(":>>> 生成的证书订单编号:{}", orderNo);
        if (super.resubmit(3L, userPO.getId(), orderNo)) {
            log.info(":>>> 有已经待支付的订单,请不要重复支付");
            throw new BusinessException("请勿重复发起支付~");
        }
        ActivityInfo activityInfo = cacheActivityService.findById(caConfig.getActivityId());
        Date date = new Date();
        OrderInfo orderInfo = new OrderInfo();
        try {
            orderInfo.setPlatform(req.getPlatform());
            orderInfo.setAppId(req.getAppId());
            orderInfo.setOpenId(req.getOpenId());
            orderInfo.setName(req.getUserAddressInfo().getRecieveName());
            orderInfo.setCaPrintName(req.getUserAddressInfo().getName());
            orderInfo.setMobile(req.getUserAddressInfo().getRecieveMobile());
            orderInfo.setProvince(req.getUserAddressInfo().getProvince());
            orderInfo.setCity(req.getUserAddressInfo().getCity());
            orderInfo.setArea(req.getUserAddressInfo().getArea());
            orderInfo.setAddress(req.getUserAddressInfo().getFullAddress());
            orderInfo.setUniversityId(req.getUniversityId());
            orderInfo.setCreatedTime(date);
            //  积分支付
            orderInfo.setMoneyType("3");
        } catch (Exception e) {
            throw new BusinessException("用户未报名活动");
        }
        if (StringUtils.isNotBlank(orderInfo.getUniversityId())) {
            Query queryU = new Query().addCriteria(Criteria.where("id").is(orderInfo.getUniversityId()));
            UniversityInfo universityInfo = mongoTemplate.findOne(queryU, UniversityInfo.class);
            if (Objects.nonNull(universityInfo)) {
                orderInfo.setUniversityName(universityInfo.getName());
            }
        }
        orderInfo.setOrderNo(orderNo);
        orderInfo.setCreatedTime(date);
        orderInfo.setStatus("1");
        orderInfo.setActivityId(caConfig.getActivityId());
        orderInfo.setPayTime(date);
        orderInfo.setPayStatus("1");
        Integer price = 0;
        Integer num = 0;
        Integer totalPrice = 0;
        Integer expressFee = 0;
        Integer discountPrice = 0;
        String expressTips = "";
        PayConfigPage payConfig = activityPayConfigService.findByActivityId(caConfig.getActivityId(), 0);
        PostageTemplate postageTemplate = null;
        if (Objects.nonNull(payConfig) && StringUtils.isNotBlank(payConfig.getPostageTemplateId())) {
            postageTemplate = postageTemplateService.findOne(payConfig.getPostageTemplateId());

        }
        List<CaInfo> caInfos = caInfoService.find(userCa.getActivityId(), userCa.getCaLevel());
        if (CollectionUtils.isEmpty(caInfos)) {
            log.error(":>>> 活动没有配置证书:{}", userCa.getActivityId());
            throw new BusinessException("活动没有配置证书");
        }
        for (CaInfo caInfo : caInfos) {
            String oorderNo = super.generateOrderNo("证书子订单");
            OOrderInfo oOrderInfo = buildOOrderInfo(caInfo, userPO, caConfig.getActivityId(), orderNo, oorderNo, false);
            discountPrice = discountPrice + (caInfo.getOriginalPrice() == null ? caInfo.getPrice() :
                    caInfo.getOriginalPrice() - caInfo.getPrice());
            orderInfo.setTitle(caInfo.getName());
            oOrderInfo.setStatus("1");
            //  积分支付
            oOrderInfo.setMoneyType("3");
            if (ArrayUtils.isEmpty(caInfo.getCertificateImages())) {
                orderInfo.setImageUrl(caInfo.getCertificateImage());
            } else {
                orderInfo.setImageUrl(caInfo.getCertificateImages()[0]);
            }

            orderInfo.setGift(caInfo.getGift());
            price = price + caInfo.getPrice();
            oOrderInfo.setSalePrice(requirePoint);
            oOrderInfo.setMoneyType("3");
            HashMap<String, Integer> ee = postageTemplateService.getOrderExpreeFee(postageTemplate,
                    orderInfo.getProvince(), caInfo.getExpressFee());
            log.info(":>>> 邮费项:{}", JSON.toJSONString(ee));
            Integer e = ee.get("fee");
            Integer extraFee = ee.get("extraFee");
            orderInfo.setExtraExpressFee(extraFee);
//            totalPrice = totalPrice + caInfo.getPrice() + e + extraFee;
            expressFee = expressFee + e;
            num = num + 1;
            oOrderInfo.setPayPrice(requirePoint / caInfos.size());
            //生成证书编号
            CaCollectReq caCollectReq = new CaCollectReq();
            caCollectReq.setCurrentUser(userPO);
            caCollectReq.setCaLevel(userCa.getCaLevel());
            caCollectReq.setTaskBizType(userCa.getCaType());
            caCollectReq.setCaTime(caConfig.getCaTime());
            caCollectReq.setCaType("2");
            caCollectReq.setActivityId(activityInfo.getId());
            caCollectReq.setCaGroupId(caInfo.getCaGroupInfoId());
            caCollectReq.setEdition(caInfo.getEdition());
            String certificateNo = caCollectService.buildCertificateNo(caCollectReq, caConfig.getLetterStart());
            oOrderInfo.setCertificateNo(certificateNo);
            mongoTemplate.insert(oOrderInfo);
            log.info(":>>> 证书:{} 邮费提示语:{}", caInfo.getId(), caInfo.getExpressFeeTips());
            if (StringUtils.isNotBlank(caInfo.getExpressFeeTips())) {
                expressTips = caInfo.getExpressFeeTips();
            }
            if (Objects.nonNull(caInfo.getGiftItems()) && !org.springframework.util.CollectionUtils.isEmpty(caInfo.getGiftItems())) {
                for (GiftCaInfo c : caInfo.getGiftItems()) {
                    String ooorderNo = super.generateOrderNo("证书子订单");
                    CaInfo caInfo1=new CaInfo();
                    BeanUtils.copyProperties(c,caInfo1);
                    OOrderInfo ooOrderInfo = buildOOrderInfo(caInfo1, userPO, caConfig.getActivityId(), orderNo, ooorderNo,
                            true);
                    ooOrderInfo.setStatus("1");
                    oOrderInfo.setMoneyType("3");
                    oOrderInfo.setPayPrice(0);
                    mongoTemplate.insert(ooOrderInfo);
                }
            }
        }
        orderInfo.setTotalFee(requirePoint);
        orderInfo.setItemPrice(requirePoint);
        orderInfo.setNum(num);
        orderInfo.setExpressFee(expressFee);
        orderInfo.setDiscountFee(discountPrice);
        orderInfo.setAccountInfoId(userPO.getId());
        orderInfo.setTips(activityInfo.getOrderTips());
        orderInfo.setCreatedTime(new Date());
        orderInfo.setExpressDesc(postageTemplate.getExpressDesc());
        if (StringUtils.isNotBlank(expressTips)) {
            orderInfo.setExpressFeeTips(expressTips);
        } else {
            orderInfo.setExpressFeeTips(postageTemplate.getExpressFeeTips());
        }
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserId(userPO.getId());
        if (Objects.nonNull(userInfoExtend)) {
            orderInfo.setSignUpMobile(userInfoExtend.getMobile());
            orderInfo.setSignUpName(userInfoExtend.getName());
            orderInfo.setUniversityId(userInfoExtend.getUniversityId());
            orderInfo.setUniversityName(userInfoExtend.getUniversityName());
            orderInfo.setMobile(userInfoExtend.getMobile());
        }

        orderInfo = mongoTemplate.insert(orderInfo);
        log.info(":>>> 订单:{},邮费提示语:{},证书配置提示语:{}", orderInfo.getOrderNo(), orderInfo.getExpressFeeTips(), expressTips);
        //扣减用户积分
        UserPointsDetail userPointsDetail = new UserPointsDetail();
        userPointsDetail.setUserId(userPO.getId());
        userPointsDetail.setOptDate(new Date());
        userPointsDetail.setAction("sub");
        userPointsDetail.setBizType("ca-receive-paper");
        userPointsDetail.setBizDesc("兑换纸质证书");
        userPointsDetail.setComments("兑换纸质证书");
        userPointsDetail.setPoints(requirePoint);
        userPointsDetail.setPlatform(userPO.getCurrentPlatform());
        userPointsService.subPoint(userPointsDetail);
        UserCaReceiveRecord userCaReceiveRecord = new UserCaReceiveRecord();
        userCaReceiveRecord.setActivityId(caConfig.getActivityId());
        userCaReceiveRecord.setCaLevel(userCa.getCaLevel());
        userCaReceiveRecord.setCaType(userCa.getCaType());
        userCaReceiveRecord.setMaterial(CaMaterialType.PAPER);
        userCaReceiveRecord.setMoneyType("3");
        userCaReceiveRecord.setReceived(true);
        userCaReceiveRecord.setReceiveTime(new Date());
        userCaReceiveRecord.setUserCaId(userCa.getId());
        userCaReceiveRecord.setComments("积分领取纸质版");
        userCaReceiveRecord.setPrice(requirePoint);
        userCaReceiveRecord.setUserId(userCa.getUserId());
        userCaReceiveRecordService.create(userCaReceiveRecord);
        return orderInfo;
    }

    @Override
    public CaCollectRes caReceive(CompetitionCaCollectRequest caCollectReq) {
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        String activityId = caCollectReq.getActivityId();
        UserPO currentUser = caCollectReq.getCurrentUser();
        Integer bizType = caCollectReq.getBizType();
        log.info("【领取电子证书】用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{}", currentUser.getId(), activityId, caType
                , caLevel);
        if (StringUtils.isBlank(activityId)) {
            throw new BusinessException("活动ID必传");
        }
        UserInfoExtend userInfoExtend = null;
        if (bizType == 1 || bizType == 3) {
            userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
            if (Objects.isNull(userInfoExtend)) {
                if (bizType == 1) {
                    new BusinessException("对不起，您未参与报名答题，不能购买");
                }
                if (bizType == 3) {
                    new BusinessException("对不起，您未报名，不能领取");
                }
            }
        } else {
            userParticipateActivityInfoService.checkUserInfoSignUp(currentUser.getId(), activityId);
            userInfoExtend = new UserInfoExtend();
            UserParticipateActivityInfo userParticipateActivityInfo =
                    userParticipateActivityInfoService.findByUserIdActivityId(currentUser.getId(), activityId);
            if (Objects.nonNull(userParticipateActivityInfo)) {
                userInfoExtend.setMobile(userParticipateActivityInfo.getMobile());
                userInfoExtend.setUserId(currentUser.getId());
                userInfoExtend.setNickName(currentUser.getNickName());
                userInfoExtend.setAvatarUrl(currentUser.getAvatarUrl());
                userInfoExtend.setUniversityId(userParticipateActivityInfo.getUniversityId());
                userInfoExtend.setUniversityName(userParticipateActivityInfo.getUniversityName());
                userInfoExtend.setName(userParticipateActivityInfo.getName());
            }
            //新业务
            UserActivityPointRanking userPointRanking =
                    userPointRankingService.findByUserIdAndActivityId(currentUser.getId(), activityId);
            if (Objects.isNull(userPointRanking) || userPointRanking.getQuantity().compareTo(40D) == -1) {
                throw new UserPointException("满40积分可免费领取电子证书，您当前积分不足");
            }
        }
        if (bizType == 3) {
            //验证用户活力值是否足够
            Double quantity = 0D;
            UserActivityPointRanking userPointRanking =
                    userPointRankingService.findByUserIdAndActivityId(currentUser.getId(), activityId);
            if (Objects.nonNull(userPointRanking)) {
                quantity = userPointRanking.getQuantity();
            }
            List<ActivityRewardRule> activityRewardRuleList = activityRewardRuleService.findByActivityId(activityId);
            if (CollectionUtils.isNotEmpty(activityRewardRuleList)) {
                Optional<ActivityRewardRule> activityRewardRuleOptional =
                        activityRewardRuleList.stream().filter(activityRewardRule -> caLevel.equals(activityRewardRule.getCaName())).findFirst();
                if (activityRewardRuleOptional.isPresent()) {
                    ActivityRewardRule activityRewardRule = activityRewardRuleOptional.get();
                    switch (activityRewardRule.getInviteOperatorType()) {
                        case "section":
                            if (caLevel.equals(activityRewardRule.getCaName()) && quantity.compareTo(activityRewardRule.getInviteStart()) == -1) {
                                log.info("【领取电子证书】用户- > {}参与活动-> {}活力值->{}满足区间section领取证书-> {}", currentUser.getId(),
                                        activityId, quantity,
                                        activityRewardRule.getCaName());
                                throw new BusinessException("当前证书未解锁，请获取足够活力值解锁后领取");
                            }
                            break;
                        case "rightInterval":
                            if (caLevel.equals(activityRewardRule.getCaName()) && quantity.compareTo(activityRewardRule.getInviteEnd()) == -1) {
                                log.info("【领取电子证书】用户- > {}参与活动-> {}活力值->{}满足区间rightInterval领取证书-> {}",
                                        currentUser.getId(), activityId, quantity, activityRewardRule.getCaName());
                                throw new BusinessException("当前证书未解锁，请获取足够活力值解锁后领取");
                            }
                            break;
                        case "equals":
                            if (caLevel.equals(activityRewardRule.getCaName()) && quantity.compareTo(activityRewardRule.getInviteEqu()) != 0) {
                                throw new BusinessException("当前证书未解锁，请获取足够活力值解锁后领取");
                            }
                            break;
//                    case "leftInterval":
//                        if(finalRewardValue <=activityRewardRule.getInviteStart()){
//                            userCaHonorRes.setCaReceivedLock(Boolean.TRUE);
//                        }
//                        userCaHonorRes.setTips(label+activityRewardRule.getInviteStart());
//                        break;
                        default:
                            throw new BusinessException("当前证书未解锁，请获取足够活力值解锁后领取");
                    }
                }

            }
        }
        UserCa userCa = this.findByUserIdAndCaTypeAndCaLevel(currentUser.getId(), caType, caLevel, activityId);
        if (Objects.isNull(userCa)) {
            throw new BusinessException("对不起，找不到您有当前领取的证书");
        }
        UserCaReceivePointRes userCaReceivePointRes = null;
        if (bizType == 1) {
            UserCaReceivePointReq userCaReceivePointReq = new UserCaReceivePointReq();
            userCaReceivePointReq.setCurrentUser(currentUser);
            userCaReceivePointReq.setActivityId(activityId);
            userCaReceivePointReq.setCaType(caType);
            userCaReceivePointReq.setCaLevel(caLevel);
            userCaReceivePointReq.setBizType("recieve-digit-ca");
            userCaReceivePointRes = userPointsService.checkReceiveCaPoint(userCaReceivePointReq);
            if (Objects.isNull(userCaReceivePointRes) || (!userCaReceivePointRes.getCaReceived() && !userCaReceivePointRes.getCaReceive())) {
                log.error("【领取电子证书】用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{} 不满足领取电子证书要求",
                        currentUser.getId(), activityId, caType, caLevel);
                throw new BusinessException("对不起，积分不满足本次领取电子证书");
            }
        }

        UserCompetition userCompetition = new UserCompetition();
        userCompetition.setUserId(currentUser.getId());
        userCompetition.setUniversityId(userInfoExtend.getUniversityId());
        userCompetition.setUniversityName(userInfoExtend.getUniversityName());
        userCompetition.setName(userInfoExtend.getName());
        userCompetition.setMobile(userInfoExtend.getMobile());
        userCompetition.setAvatarUrl(userInfoExtend.getAvatarUrl());
        userCompetition.setNickName(userInfoExtend.getNickName());
        CaCollectRes caCollectRes = userCompetitionQaCaService.commonCaReceive(currentUser, activityId, caType,
                caLevel, userCompetition);
        Boolean userReceive = Boolean.FALSE;
        if (caCollectReq.getBizType() == 3) {
            userReceive = userCaReceiveRecordService.existCaByUserIdAndCaTypeAndLevelActivityId(currentUser.getId(),
                    caType, caLevel,
                    activityId, CaMaterialType.DIGIT);
        } else {
            //判断用户是否已领取电子版，如果领取过。则不重新计算扣减积分
            userReceive = userCaReceiveRecordService.existCaByUserIdAndCaTypeAndActivityId(currentUser.getId(), caType,
                    activityId, CaMaterialType.DIGIT);
        }
        if (!userReceive) {
            Date now = new Date();
            //记录用户领取记录
            UserCaReceiveRecord userCaReceiveRecord = new UserCaReceiveRecord();
            userCaReceiveRecord.setActivityId(activityId);
            userCaReceiveRecord.setCaType(caType);
            userCaReceiveRecord.setCaLevel(caLevel);
            userCaReceiveRecord.setMaterial(CaMaterialType.DIGIT);
            userCaReceiveRecord.setMoneyType("3");
            userCaReceiveRecord.setUserCaId(userCa.getId());
            userCaReceiveRecord.setReceiveTime(now);
            userCaReceiveRecord.setUserId(currentUser.getId());
            userCaReceiveRecordService.create(userCaReceiveRecord);

            UserCaReceiveHistory userCaReceiveHistory = new UserCaReceiveHistory();
            userCaReceiveHistory.setActivityId(activityId);
            ActivityInfo activityInfo = cacheActivityService.findById(activityId);
            userCaReceiveHistory.setActivityName(activityInfo.getName());
            userCaReceiveHistory.setUserId(currentUser.getId());
            userCaReceiveHistory.setCaType(caType);
            userCaReceiveHistory.setCaLevel(caLevel);
            userCaReceiveHistory.setCaTemplateId(caCollectRes.getCaTemplate().getId());
            userCaReceiveHistory.setCaTemplateImgUrl(caCollectRes.getCaTemplate().getBackgroundPic().getUrl());
            userCaReceiveHistory.setAppId(currentUser.getAppId());
            userCaReceiveHistory.setPlatform(currentUser.getCurrentPlatform());
            userCaReceiveHistory.setReceiveTime(caCollectRes.getCaTime());
            userCaReceiveHistoryService.saveOrUpdate(userCaReceiveHistory);
            if (caCollectReq.getBizType() == 1) {
                //扣减用户积分
                UserPointsDetail userPointsDetail = new UserPointsDetail();
                userPointsDetail.setUserId(currentUser.getId());
                userPointsDetail.setOptDate(now);
                userPointsDetail.setAction("sub");
                userPointsDetail.setBizType("ca-receive-digit");
                userPointsDetail.setBizDesc("兑换电子证书");
                userPointsDetail.setComments("兑换电子证书");
                userPointsDetail.setPlatform(currentUser.getCurrentPlatform());
                if (Objects.nonNull(userCaReceivePointRes)) {
                    userPointsDetail.setPoints(userCaReceivePointRes.getCurrentSubPoint());
                    userPointsService.subPoint(userPointsDetail);
                }

            }
        }
        return caCollectRes;
    }

    @Override
    public CaCollectRes caCollectContest(CompetitionCaCollectRequest caCollectReq) {
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        String activityId = caCollectReq.getActivityId();
        UserPO currentUser = caCollectReq.getCurrentUser();
        String caReceiveType = caCollectReq.getCaReceiveType();
        log.info("【竞赛领取电子证书】用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{}", currentUser.getId(), activityId, caType
                , caLevel);
        if (StringUtils.isBlank(activityId)) {
            throw new BusinessException("活动ID必传");
        }
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
        UserParticipateActivityInfo userParticipateActivityInfo =
                userParticipateActivityInfoService.findByUserIdActivityId(currentUser.getId(), activityId);
        if (Objects.isNull(userInfoExtend) || Objects.isNull(userParticipateActivityInfo)) {
            throw new BusinessException("对不起，你未报名,不能领取电子证书");
        }
        Integer point = 0;
        UserActivityPointRanking userPointRanking =
                userPointRankingService.findByUserIdAndActivityId(currentUser.getId(), activityId);
        if (Objects.nonNull(userPointRanking)) {
            point = userPointRanking.getQuantity().intValue();
        }
        ActivityInfo activityInfo = cacheActivityService.findById(activityId);
        CertificateReceiveLimit certificateReceiveLimit = activityInfo.getCertificateReceiveLimit();
        if (Objects.isNull(certificateReceiveLimit)) {
            throw new BusinessException("证书领取限制配置未配置");
        }

        List<UserCa> userCaList = this.findByUserIdAndActivityId(currentUser.getId(), activityId);
        if (CollectionUtils.isEmpty(userCaList)) {
            String certificateMsg = "";
            if ("qa".equals(caReceiveType)) {
                certificateMsg = "您当前还未获得证书，请先去答题获得证书";
            } else {
                certificateMsg = "您当前还未获得证书，请先去邀请好友获得证书";
            }
            throw new NotExistCertificateException(certificateMsg);
        }

        //当前贡献值小于
        if ((point == 0 || certificateReceiveLimit.getCaCertificateValue() == 0) || (point < certificateReceiveLimit.getCaCertificateValue())) {
            throw new PointReceiveCertificateException("领取电子版需" + certificateReceiveLimit.getCaCertificateValue() + activityInfo.getRewardValueAlias() + "，请先去获取" + activityInfo.getRewardValueAlias());
        }
        long count =
                userCaList.stream().filter(userCa -> userCa.getCaType().equals(caType) && userCa.getCaLevel().equals(caLevel)).count();
        if (count == 0) {
            throw new BusinessException("对不起未找到要领取的电子证书");
        }
        if (caCollectReq.getBizType() == 4) {
            return null;
        }
        UserCompetition userCompetition = new UserCompetition();
        userCompetition.setUserId(currentUser.getId());
        userCompetition.setUniversityId(userInfoExtend.getUniversityId());
        userCompetition.setUniversityName(userInfoExtend.getUniversityName());
        userCompetition.setName(userInfoExtend.getName());
        userCompetition.setMobile(userInfoExtend.getMobile());
        userCompetition.setNickName(userInfoExtend.getNickName());
        userCompetition.setAvatarUrl(userInfoExtend.getAvatarUrl());
        CaCollectRes caCollectRes = userCompetitionQaCaService.commonCaReceive(currentUser, activityId, caType,
                caLevel, userCompetition);
        UserCaReceiveHistory userCaReceiveHistory = new UserCaReceiveHistory();
        userCaReceiveHistory.setActivityId(activityId);
        userCaReceiveHistory.setActivityName(activityInfo.getName());
        userCaReceiveHistory.setUserId(currentUser.getId());
        userCaReceiveHistory.setCaLevel(caLevel);
        userCaReceiveHistory.setCaType(caType);
        userCaReceiveHistory.setCaTemplateId(caCollectRes.getCaTemplate().getId());
        userCaReceiveHistory.setCaTemplateImgUrl(caCollectRes.getCaTemplate().getBackgroundPic().getUrl());
        userCaReceiveHistory.setReceiveTime(caCollectRes.getCaTime());
        userCaReceiveHistory.setAppId(currentUser.getAppId());
        userCaReceiveHistory.setPlatform(currentUser.getCurrentPlatform());
        userCaReceiveHistoryService.saveOrUpdate(userCaReceiveHistory);
        return caCollectRes;
    }

    @Override
    public UserCaHonorRes checkReceivePaperCollectContest(CompetitionCaCollectRequest caCollectReq) {
        UserPO currentUser = caCollectReq.getCurrentUser();
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        String activityId = caCollectReq.getActivityId();
        String caReceiveType = caCollectReq.getCaReceiveType();
        log.info("【竞赛纸质领取证书】用户 ->{} 参与活动->{} 领取纸质证书 caType-> {} | caLevel->{}", currentUser.getId(), activityId,
                caType
                , caLevel);
        if (StringUtils.isBlank(activityId)) {
            throw new BusinessException("活动ID必传");
        }
        UserParticipateActivityInfo userParticipateActivityInfo =
                userParticipateActivityInfoService.findByUserIdActivityId(currentUser.getId(), activityId);
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
        if (Objects.isNull(userInfoExtend) || Objects.isNull(userParticipateActivityInfo)) {
            throw new BusinessException("对不起，你未报名,不能领取电子证书");
        }
        Integer point = 0;
        UserActivityPointRanking userPointRanking =
                userPointRankingService.findByUserIdAndActivityId(currentUser.getId(), activityId);
        if (Objects.nonNull(userPointRanking)) {
            point = userPointRanking.getQuantity().intValue();
        }
        log.info("【竞赛纸质领取证书】用户 ->{} 参与竞赛活动-> {}获得贡献值-> {}", currentUser.getId(), activityId, point);
        ActivityInfo activityInfo = cacheActivityService.findById(activityId);
        CertificateReceiveLimit certificateReceiveLimit = activityInfo.getCertificateReceiveLimit();
        if (Objects.isNull(certificateReceiveLimit)) {
            throw new BusinessException("证书领取限制配置未配置");
        }
        List<UserCa> userCaList = this.findByUserIdAndActivityId(currentUser.getId(), activityId);
        if (CollectionUtils.isEmpty(userCaList)) {
            String certificateMsg = "";
            if ("qa".equals(caReceiveType)) {
                certificateMsg = "您当前还未获得证书，请先去答题获得证书";
            } else {
                certificateMsg = "您当前还未获得证书，请先去邀请好友获得证书";
            }
            log.error("【竞赛纸质领取证书】用户 ->{} 参与竞赛活动-> {}获得贡献值-> {} 未获取到证书-> {}", currentUser.getId(), activityId, point,
                    certificateMsg);
            throw new NotExistCertificateException(certificateMsg);
        }
        long countExist =
                userCaList.stream().filter(userCa -> userCa.getCaType().equals(caType) && userCa.getCaLevel().equals(caLevel)).count();
        if (countExist == 0) {
            throw new BusinessException("对不起未找到要领取纸质证书");
        }
        Integer paperCertificateValue = certificateReceiveLimit.getPaperCertificateValue();
        //领取当前贡献值小于
        if ((point == 0 || paperCertificateValue == 0) || point < paperCertificateValue) {
            log.error("【竞赛纸质领取证书】用户 ->{} 参与竞赛活动-> {}获得贡献值-> {} 领取纸质证书贡献值不足- >{}", currentUser.getId(), activityId,
                    point, certificateReceiveLimit.getPaperCertificateValue());
            throw new PointReceiveCertificateException("领取纸质版需" + paperCertificateValue + activityInfo.getRewardValueAlias() + "，请先去获取" + activityInfo.getRewardValueAlias());
        }
        List<MyOrderResponse> myOrderList = orderService.findByUserAndActivityId(currentUser, activityId);
        UserCaHonorRes userCaHonor = new UserCaHonorRes();
        Integer count = point / paperCertificateValue;
        if (CollectionUtils.isEmpty(myOrderList)) {
            userCaHonor.setMessageTips("每达到" + paperCertificateValue + activityInfo.getRewardValueAlias() +
                    "，可领取一本纸质证书，您还可领取" + count +
                    "次，是否确认领取");
            userCaHonor.setPaperReceivedLock(Boolean.TRUE);
            return userCaHonor;
        }
        //获取是否领取纸质证书
        Optional<MyOrderResponse> myOrderOptional =
                myOrderList.stream().filter(myOrder -> myOrder.getCaLevel().equals(caLevel) && myOrder.getCaType().equals(caType)).findFirst();
        if (myOrderOptional.isPresent()) {
            userCaHonor.setMessageTips("您已领取过当前等级纸质证书");
            userCaHonor.setPaperReceived(Boolean.TRUE);
            userCaHonor.setOrderNo(myOrderOptional.get().getOrderNo());
            userCaHonor.setPaperReceivedLock(Boolean.TRUE);
            return userCaHonor;
        }
        if (myOrderList.size() >= count) {
            userCaHonor.setMessageTips("每达到" + paperCertificateValue + activityInfo.getRewardValueAlias() +
                    "，可领取一本纸质证书，您的剩余次数不足");
            return userCaHonor;
        }
        userCaHonor.setMessageTips("每达到" + paperCertificateValue + activityInfo.getRewardValueAlias() +
                "，可领取一本纸质证书，您还可领取" + (count - myOrderList.size()) +
                "次，是否确认领取");
        userCaHonor.setPaperReceivedLock(Boolean.TRUE);
        return userCaHonor;
    }

    @Override
    public UserCaDomain getUserCaInfo(@NotNull String id, @NotNull String userId) {
        log.info(":>>> 开始获取用户证书信息:{},userId:{}", id, userId);
        UserCa userCa = this.findOne(id);
        if (Objects.isNull(userCa)) {
            log.error(":>>> 用户证书:{} 不存在", id);
            throw new BusinessException("用户证书不存在");
        }
        UserCaDomain userCaDomain = new UserCaDomain();
        UserAddressInfo userAddressInfo = userAddressInfoService.findByUserId(userId);
        if (Objects.nonNull(userAddressInfo)) {
            BeanUtils.copyProperties(userAddressInfo, userCaDomain);
            userCaDomain.setUserAddressInfoId(userAddressInfo.getUserId());
        }
        userCaDomain.setCaLeve(userCa.getCaLevel());
        userCaDomain.setUserId(userId);
        UserInfoExtend extend = userInfoExtendService.findByUserId(userId);
        if (Objects.nonNull(extend)) {
            userCaDomain.setName(extend.getName());
            userCaDomain.setMobile(extend.getMobile());
            userCaDomain.setUniversityId(extend.getUniversityId());
            userCaDomain.setUniversityName(extend.getUniversityName());
        }
        return userCaDomain;
    }

    @Override
    public UserCa findOne(@NotNull String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, UserCa.class);
    }

    private OOrderInfo buildOOrderInfo(CaInfo caInfo, UserPO userPO,
                                       String activityId, String orderNo,
                                       String oorderNo, boolean gift) {
        OOrderInfo oOrderInfo = new OOrderInfo();
        oOrderInfo.setOrderNo(orderNo);
        oOrderInfo.setOOrderNo(oorderNo);
        oOrderInfo.setCreatedTime(new Date());
        oOrderInfo.setAccountInfoId(userPO.getId());
        if (ArrayUtils.isEmpty(caInfo.getCertificateImages())) {
            oOrderInfo.setImageUrl(caInfo.getCertificateImage());
        } else {
            oOrderInfo.setImageUrl(caInfo.getCertificateImages()[0]);
        }

        oOrderInfo.setCaInfo(caInfo);
        oOrderInfo.setItemType("ca");
        oOrderInfo.setItemInfoId(caInfo.getId());
        oOrderInfo.setStatus("0");
        oOrderInfo.setItemTitle(caInfo.getName());
        if (ArrayUtils.isEmpty(caInfo.getCertificateImages())) {
            oOrderInfo.setItemImageUrl(caInfo.getCertificateImage());
        } else {
            oOrderInfo.setItemImageUrl(caInfo.getCertificateImages()[0]);
        }
        oOrderInfo.setSalePrice(caInfo.getPrice());
        oOrderInfo.setItemPrice(caInfo.getOriginalPrice());
        oOrderInfo.setAppId(userPO.getAppId());
        oOrderInfo.setOpenId(userPO.getOpenId());
        oOrderInfo.setExpressFee(caInfo.getExpressFee().toString());
        oOrderInfo.setPlatform("wechat-h5");
        oOrderInfo.setCaGift(caInfo.getCaGift());
        oOrderInfo.setNum(1);
        oOrderInfo.setOpenId(userPO.getOpenId());
        oOrderInfo.setActivityId(activityId);
        oOrderInfo.setGift(caInfo.getGift());
        if (gift) {
            oOrderInfo.setGifted(true);
            oOrderInfo.setSalePrice(0);
            oOrderInfo.setItemPrice(0);
            oOrderInfo.setSalePriceBack(caInfo.getPrice());
            oOrderInfo.setItemPriceBack(caInfo.getOriginalPrice());
            oOrderInfo.setItemPrice(0);
        } else {
            oOrderInfo.setGifted(false);
        }
        return oOrderInfo;
    }

    public void checkCaReceive(String activityId, String userId) {
        if (StringUtils.isBlank(activityId) || StringUtils.isBlank(userId)) {
            log.error("【领取电子证书】校验用户参与活动参数错误 activityId ->{} userId ->{}", activityId, userId);
            throw new BusinessException("参数错误");
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        boolean exists = this.mongoTemplate.exists(query, UserCa.class);
        if (!exists) {
            throw new CaReceiveNotFoundException("请选择相应方式获取证书");
        }
    }

    @Async
    @Override
    public void updateByUserId(UserInfoExtend userInfoExtend) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userInfoExtend.getUserId()));
        Update update = new Update();
        update.set("name", userInfoExtend.getName());
        update.set("mobile", userInfoExtend.getMobile());
        update.set("universityName", userInfoExtend.getUniversityName());
        update.set("universityId", userInfoExtend.getUniversityId());
        update.set("grade", userInfoExtend.getGrade());
        update.set("updatedTime", new Date());
        this.mongoTemplate.updateMulti(query, update, UserCa.class);


    }

    @Override
    public UserCa findByUserIdAndCaTypeAndCaLevel(String userId, String caType,
                                                  String caLevel, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("caType").is(caType));
        query.addCriteria(Criteria.where("caLevel").is(caLevel));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return this.masterMongoTemplate.findOne(query, UserCa.class);

    }

    @Override
    public List<UserCa> findByUserIdAndActivityId(String userId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return this.mongoTemplate.find(query, UserCa.class);
    }

    @Override
    public List<UserCaHonorRes> findByActivityId(UserPO currentUser, String activityId) {
        String userId = currentUser.getId();
        Integer rewardValue = 0;
        UserActivityPointRanking userActivityPointRanking =
                userActivityPointRankingService.findByUserIdAndActivityId(userId, activityId);
        if (Objects.nonNull(userActivityPointRanking)) {
            rewardValue = userActivityPointRanking.getQuantity().intValue();
        }
        List<UserCaHonorRes> list = caCertificateConfigService.findByActivityId(activityId);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<ActivityRewardRule> activityRewardRuleList = activityRewardRuleService.findByActivityId(activityId);
        if (CollectionUtils.isEmpty(activityRewardRuleList)) {
            return list;
        }
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
        if (Objects.isNull(userInfoExtend)) {
            userInfoExtend = new UserInfoExtend();
        }
        List<MyOrderResponse> myOrderList = orderService.findByUserAndActivityId(currentUser, activityId);
        final String label = "需活力值达到";
        Integer finalRewardValue = rewardValue;
        Integer count = finalRewardValue / 1000;
        UserInfoExtend finalUserInfoExtend = userInfoExtend;
        final String msgTips = "当前证书未解锁，请获取足够活力值解锁后领取";
        list.stream().forEach(userCaHonorRes -> {
            Optional<ActivityRewardRule> activityRewardRuleOptional =
                    activityRewardRuleList.stream().filter(activityRewardRule -> userCaHonorRes.getCaLevel().equals(activityRewardRule.getCaName())).findFirst();
            if (activityRewardRuleOptional.isPresent()) {
                ActivityRewardRule activityRewardRule = activityRewardRuleOptional.get();
                userCaHonorRes.setSort(activityRewardRule.getPriority());
                switch (activityRewardRule.getInviteOperatorType()) {
                    case "section":
                        if (finalRewardValue >= activityRewardRule.getInviteStart().intValue()) {
                            userCaHonorRes.setCaReceivedLock(Boolean.TRUE);
                            log.info("【我的荣誉】用户- > {}参与活动-> {}活力值->{}满足区间section领取证书-> {}", userId, activityId,
                                    finalRewardValue, activityRewardRule.getCaName());
                        }
                        userCaHonorRes.setTips(label + activityRewardRule.getInviteStart().intValue());
                        break;
                    case "rightInterval":
                        if (finalRewardValue >= activityRewardRule.getInviteEnd().intValue()) {
                            userCaHonorRes.setCaReceivedLock(Boolean.TRUE);
                            log.info("【我的荣誉】用户- > {}参与活动-> {}活力值->{}满足区间rightInterval领取证书-> {}", userId, activityId,
                                    finalRewardValue, activityRewardRule.getCaName());
                        }
                        userCaHonorRes.setTips(label + activityRewardRule.getInviteEnd().intValue());
                        break;
                    case "equals":
                        if (finalRewardValue.equals(activityRewardRule.getInviteEqu().intValue())) {
                            userCaHonorRes.setCaReceivedLock(Boolean.TRUE);
                        }
                        userCaHonorRes.setTips(label + activityRewardRule.getInviteEqu().intValue());
                        break;
//                    case "leftInterval":
//                        if(finalRewardValue <=activityRewardRule.getInviteStart()){
//                            userCaHonorRes.setCaReceivedLock(Boolean.TRUE);
//                        }
//                        userCaHonorRes.setTips(label+activityRewardRule.getInviteStart());
//                        break;
                    default:
                }
                if (userCaHonorRes.getCaReceivedLock() && finalRewardValue >= 1000) {//纸质证书大于1000
                    if (CollectionUtils.isNotEmpty(myOrderList)) {
                        //获取是否领取纸质证书
                        Optional<MyOrderResponse> myOrderOptional =
                                myOrderList.stream().filter(myOrder -> myOrder.getCaLevel().equals(userCaHonorRes.getCaLevel()) && myOrder.getCaType().equals(userCaHonorRes.getCaType())).findFirst();
                        if (myOrderOptional.isPresent()) {
                            userCaHonorRes.setMessageTips("您已领取过当前证书纸质版");
                            userCaHonorRes.setPaperReceived(Boolean.TRUE);
                            userCaHonorRes.setOrderNo(myOrderOptional.get().getOrderNo());
                            userCaHonorRes.setPaperReceivedLock(Boolean.TRUE);
                        } else {
                            //未领取过
                            if (myOrderList.size() < count) {
                                Integer receiveCount = count - myOrderList.size();
                                userCaHonorRes.setMessageTips("每满1000活力值，可免费领取一本纸质证书，您还可免费领取" + receiveCount +
                                        "次，是否确认领取");
                                userCaHonorRes.setPaperReceivedLock(Boolean.TRUE);
                            } else {
                                if (myOrderList.size() >= count) {
                                    userCaHonorRes.setMessageTips("每满1000活力值，可免费领取一本纸质证书，您的剩余次数不足");
                                }
                            }

                        }
                    } else {
                        userCaHonorRes.setMessageTips("每满1000活力值，可免费领取一本纸质证书，您还可免费领取" + count +
                                "次，是否确认领取");
                        userCaHonorRes.setPaperReceivedLock(Boolean.TRUE);
                    }
                } else {
                    userCaHonorRes.setMessageTips("每满1000活力值，可免费领取一本纸质证书，您当前活力值不足");
                }
            }
            if (!userCaHonorRes.getCaReceivedLock() && !userCaHonorRes.getPaperReceivedLock()) {
                userCaHonorRes.setMessageTips("当前证书未解锁，请获取足够活力值解锁后领取");
            }
            if (userCaHonorRes.getCaReceivedLock()) {
                UserCa userCa = new UserCa();
                userCa.setUserId(currentUser.getId());
                userCa.setTaskBizType("invite");
                userCa.setUniversityId(finalUserInfoExtend.getUniversityId());
                userCa.setUniversityName(finalUserInfoExtend.getUniversityName());
                userCa.setMobile(finalUserInfoExtend.getMobile());
                userCa.setName(finalUserInfoExtend.getName());
                userCa.setCaType(userCaHonorRes.getCaType());
                userCa.setCaLevel(userCaHonorRes.getCaLevel());
                userCa.setActivityId(activityId);
                userCa.setGrade(finalUserInfoExtend.getGrade());
                userCa.setAppId(finalUserInfoExtend.getAppId());
                userCa.setPlatform(finalUserInfoExtend.getPlatform());
                userCa.setPlatform(currentUser.getCurrentPlatform());
                userCa.setAppId(currentUser.getAppId());
                this.create(userCa);
            } else {
                userCaHonorRes.setCaMessageTips(msgTips);
            }
        });
        if (CollectionUtils.isNotEmpty(myOrderList)) {
            myOrderList.clear();
        }
        //升序按等级小输出
        return list.stream().sorted(Comparator.comparing(UserCaHonorRes::getSort)).collect(Collectors.toList());
    }

    @Override
    public CaCollectRes caMiniReceive(CompetitionCaCollectRequest caCollectReq) {
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        String activityId = caCollectReq.getActivityId();
        UserPO currentUser = caCollectReq.getCurrentUser();
        String caReceiveType = caCollectReq.getCaReceiveType();
        String userId = currentUser.getId();
        log.info("【微信小程序领取电子证书】用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{}", userId, activityId,
                caType
                , caLevel);
        ActivityInfo activityInfo = activityService.findOne(activityId);
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
        UserParticipateActivityInfo userParticipateActivityInfo =
                userParticipateActivityInfoService.findReceiveCaUserByUserIdActivityId(currentUser.getId(), activityId);
        if (Objects.isNull(userInfoExtend) || Objects.isNull(userParticipateActivityInfo)) {
            throw new BusinessException("对不起，你未报名,不能领取电子证书");
        }
        if (userInfoExtend.checkUserInfo()) {
            throw new BusinessException("对不起，个人信息不整不能领取电子证书");
        }
        UserCa userCa = this.findByUserIdAndCaTypeAndCaLevel(currentUser.getId(), caType, caLevel, activityId);
        if (Objects.isNull(userCa)) {
            log.error("【微信小程序领取电子证书-】未找到 用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{}", currentUser.getId(),
                    activityId,
                    caType
                    , caLevel);
            throw new BusinessException("对不起，找不到您有当前领取的证书");
        }
        if ("video".equals(activityInfo.getType()) && caCollectReq.getBizType() == 1) {
            ActivityCourse activityCourse = mongoTemplate.findById(activityInfo.getCourseId(), ActivityCourse.class);
            if (Objects.isNull(activityCourse)) {
                throw new BusinessException("课程信息不存在");
            }
            Integer courseStatus = userVideoService.getActivityStatus(userId, currentUser.getAppId(), activityId);
            log.info("【电子证书-课程状态】获取用户购买课程状态 currentUser - > {} |  courseStatus- >{}", userId, courseStatus);
            if (courseStatus < ActivityVideoStatusEnum.DO_THE_TITLE.getType()) {
                log.error("【不满足领取电子-课程状态】 currentUser - > {} |  courseStatus- >{} | activityId -> {}", userId,
                        courseStatus
                        , activityId);
                throw new BusinessException("对不起，不满足领取电子证书条件");
            }
        }
        //验证用户领取是否已支付领取电子电子证书竞赛答题证书
         if("qa".equals(userCa.getTaskBizType())&&activityInfo.getContestDigitalCaFee()>0){
             DigitalCaOrder digitalCaOrder = digitalCaOrderDetailService.findByUserIdAndCaTypeAndCaLevel(caCollectReq);
             if(Objects.isNull(digitalCaOrder)){
                 log.error("【微信小程序领取电子证书-】UserCaServiceImpl.caMiniReceive 未下单购买 用户 ->{} 参与活动->{} 领取电子证书 caType-> {} |" +
                                 " " +
                                 "caLevel->{}",
                         currentUser.getId(),
                         activityId,
                         caType
                         , caLevel);
                 throw new BusinessException("对不起，未支付当前电子证书,不能参与领取");
             }
         }
        //领取电子证书
        UserCompetition userCompetition = new UserCompetition();
        userCompetition.setUserId(userId);
        userCompetition.setUniversityId(userParticipateActivityInfo.getUniversityId());
        userCompetition.setUniversityName(userParticipateActivityInfo.getUniversityName());
        userCompetition.setMobile(userParticipateActivityInfo.getMobile());
        userCompetition.setName(userParticipateActivityInfo.getName());
        userCompetition.setNickName(userParticipateActivityInfo.getNickName());
        userCompetition.setAvatarUrl(currentUser.getAvatarUrl());
        CaCollectRes caCollectRes = userCompetitionQaCaService.commonCaReceive(currentUser, activityId, caType,
                caLevel, userCompetition);
        //新增电子证书领取历史记录
        UserCaReceiveHistory userCaReceiveHistory = new UserCaReceiveHistory();
        userCaReceiveHistory.setUserId(userId);
        userCaReceiveHistory.setActivityId(activityId);
        userCaReceiveHistory.setActivityName(activityInfo.getName());
        userCaReceiveHistory.setCaLevel(caLevel);
        userCaReceiveHistory.setCaTemplateImgUrl(caCollectRes.getCaTemplate().getBackgroundPic().getUrl());
        userCaReceiveHistory.setCaType(caType);
        userCaReceiveHistory.setCaTemplateId(caCollectRes.getCaTemplate().getId());
        userCaReceiveHistory.setReceiveTime(caCollectRes.getCaTime());
        userCaReceiveHistory.setAppId(currentUser.getAppId());
        userCaReceiveHistory.setPlatform(currentUser.getCurrentPlatform());
        userCaReceiveHistoryService.saveOrUpdate(userCaReceiveHistory);
        caCollectRes.setActivityType(activityInfo.getType());
        //需要英文名称
        if(ActivityInfo.DIGITAL_ENGLISH_CA.equals(activityInfo.getDigitalCaType())){
            if(StringUtils.isNotBlank(userParticipateActivityInfo.getEnName())){
                caCollectRes.setUserName(userParticipateActivityInfo.getEnName());
            }else{
                String pinYinName = caPinYinService.getPinYinNameByUserId(activityId, userInfoExtend);
                if(StringUtils.isNotBlank(pinYinName)){
                    caCollectRes.setUserName(pinYinName);
                    userInfoExtend.setEnName(pinYinName);
                    userParticipateActivityInfo.setEnName(pinYinName);
                    this.mongoTemplate.save(userInfoExtend);
                    this.mongoTemplate.save(userParticipateActivityInfo);
                }
            }
            UniversityInfo universityInfo = universityService.get(userParticipateActivityInfo.getUniversityId());
            if(Objects.nonNull(universityInfo)){
                if(StringUtils.isNotBlank(universityInfo.getEnName())){
                    caCollectRes.setUniversityName(universityInfo.getEnName());
                }
            }
        }
        return caCollectRes;
    }

    @Override
    public CaCollectRes caReceiveHistory(CompetitionCaCollectRequest caCollectReq) {
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        UserPO currentUser = caCollectReq.getCurrentUser();
        String activityId = caCollectReq.getActivityId();
        String caReceiveType = caCollectReq.getCaReceiveType();
        String userId = currentUser.getId();
        log.info("【微信小程序领取电子证书】用户 ->{} 参与活动->{} 领取电子证书 caType-> {} | caLevel->{}", userId, activityId,
                caType
                , caLevel);
        ActivityInfo activityInfo = activityService.findOne(activityId);
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserIdAndAppId(currentUser);
        UserParticipateActivityInfo userParticipateActivityInfo =
                userParticipateActivityInfoService.findByUserIdActivityId(currentUser.getId(), activityId);
        if (Objects.isNull(userInfoExtend) || Objects.isNull(userParticipateActivityInfo)) {
            throw new BusinessException("对不起，你未报名,不能领取电子证书");
        }
        if (userInfoExtend.checkUserInfo()) {
            throw new BusinessException("对不起，个人信息不整不能领取电子证书");
        }

        //领取电子证书
        UserCompetition userCompetition = new UserCompetition();
        userCompetition.setUserId(userId);
        userCompetition.setUniversityId(userParticipateActivityInfo.getUniversityId());
        userCompetition.setUniversityName(userParticipateActivityInfo.getUniversityName());
        userCompetition.setMobile(userParticipateActivityInfo.getMobile());
        userCompetition.setNickName(userParticipateActivityInfo.getNickName());
        userCompetition.setName(userParticipateActivityInfo.getName());
        userCompetition.setAvatarUrl(currentUser.getAvatarUrl());
        CaCollectRes caCollectRes = userCompetitionQaCaService.commonCaReceive(currentUser, activityId, caType,
                caLevel, userCompetition);
        caCollectRes.setActivityType(activityInfo.getType());
        //需要英文名称
        if(ActivityInfo.DIGITAL_ENGLISH_CA.equals(activityInfo.getDigitalCaType())){
            if(StringUtils.isNotBlank(userParticipateActivityInfo.getEnName())){
                caCollectRes.setUserName(userParticipateActivityInfo.getEnName());
            }else{
                String pinYinName = caPinYinService.getPinYinNameByUserId(activityId, userInfoExtend);
                if(StringUtils.isNotBlank(pinYinName)){
                    userInfoExtend.setEnName(pinYinName);
                    caCollectRes.setUserName(pinYinName);
                    userParticipateActivityInfo.setEnName(pinYinName);
                    this.mongoTemplate.save(userInfoExtend);
                    this.mongoTemplate.save(userParticipateActivityInfo);
                }
            }
            UniversityInfo universityInfo = universityService.get(userParticipateActivityInfo.getUniversityId());
            if(Objects.nonNull(universityInfo)){
                if(StringUtils.isNotBlank(universityInfo.getEnName())){
                    caCollectRes.setUniversityName(universityInfo.getEnName());
                }
            }
        }
        return caCollectRes;
    }

    @Override
    public List<UserCaReceiveHistoryService.UserCaReceiveActivity> userCaList(UserPO currentUser) {
        log.info("【获取所有电子证书】- > {}", currentUser.getId());
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
        List<UserCa> userCaList = this.mongoTemplate.find(query, UserCa.class);
        if (CollectionUtils.isEmpty(userCaList)) {
            return new ArrayList<>();
        }
        Date now = new Date();
        List<UserCa> caList = userCaList.stream().filter(userCa -> userCa.getCreatedTime().toInstant().plus(90L,
                ChronoUnit.DAYS).isAfter(now.toInstant())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(caList)) {
            log.warn("【获取所有电子证书】- > {} 已超过90天证书", currentUser.getId());
            return new ArrayList<>();
        }
        UserCaReceiveHistoryService userCaReceiveHistory = new UserCaReceiveHistoryService();
        List<UserCaReceiveHistoryService.UserCaReceiveActivity> userCaListResult = Lists.newLinkedList();
        Map<String, List<UserCa>> userCaMap = caList.stream().collect(Collectors.groupingBy(UserCa::getActivityId));
        userCaMap.forEach((activityId, userCaItem) -> {
            ActivityInfo activityInfo = cacheActivityService.findById(activityId);
            UserCaReceiveHistoryService.UserCaReceiveActivity userCaReceiveActivity =
                    userCaReceiveHistory.new UserCaReceiveActivity();
            userCaReceiveActivity.setActivityId(activityId);
            userCaReceiveActivity.setActivityName(activityInfo.getName());
            List<UserCa> sortUserCaItem =
                    userCaItem.stream().sorted(Comparator.comparing(UserCa::getCreatedTime).reversed()).collect(Collectors.toList());
            userCaReceiveActivity.setCaReceiveHistoryList(sortUserCaItem.stream().map(userCa -> {
                UserCaReceiveHistory userCaReceive = new UserCaReceiveHistory();
                userCaReceive.setActivityId(activityId);
                userCaReceive.setActivityName(activityInfo.getName());
                userCaReceive.setUserId(userCa.getUserId());
                userCaReceive.setCaType(userCa.getCaType());
                userCaReceive.setCaLevel(userCa.getCaLevel());
                CaCertificateConfig caCertificateConfig =
                        caCertificateConfigService.findByActivityIdAndCaTypeAndCaLevel(activityId, userCa.getCaType()
                                , userCa.getCaLevel());
                if (Objects.nonNull(caCertificateConfig)) {
                    userCaReceive.setCaTemplateId(caCertificateConfig.getTemplateId());
                    CaTemplate caTemplate = mongoTemplate.findById(caCertificateConfig.getTemplateId(),
                            CaTemplate.class);
                    if (Objects.nonNull(caTemplate)) {
                        userCaReceive.setCaTemplateImgUrl(caTemplate.getBackgroundPic().getUrl());
                    }
                }
                return userCaReceive;
            }).collect(Collectors.toList()));
            userCaListResult.add(userCaReceiveActivity);
        });
        userCaMap.clear();
        return userCaListResult;
    }

    @Override
    public void removeUserCaByUserIdAndActivityId(String userId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        Update update = new Update();
        update.set("userId", userId + "delete");
        update.set("activityId", activityId + "delete");
        update.set("updatedTime", new Date());
        this.mongoTemplate.updateMulti(query, update, UserCa.class);

        this.mongoTemplate.updateMulti(query, update, UserCaReceiveHistory.class);
    }

    @Override
    public List<UserCa> findByUserIdAndActivityIdAndTaskBizType(String userId, String activityId, String taskBizType) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        query.addCriteria(Criteria.where("taskBizType").is(taskBizType));
        return this.mongoTemplate.find(query, UserCa.class);
    }
}
